﻿
using System.Collections.Generic;
using System.Text;
namespace FluentTagsGenerator
{
    class AttributeMethodGenerator
    {

        const string attributeMethodTemplate = @"
        public ${Class}Tag ${AttributeMethodName}(${Type} value)
        {   ${processing}
            Attributes.Add(""${Attribute}"", value.ToString());
            return this;
        }
        ";

        const string genericAttribuiteMethodTemplate = @"
        public ${Class}Tag<ParentType> ${AttributeMethodName}(${Type} value)
        {   ${processing}
            Attributes.Add(""${Attribute}"", value.ToString());
            return this;
        }
        ";

        const string attributeIntGetterTemplate = @"
        public ${Type} ${AttributeMethodName}Attribute
        {
            get
            {
                ${Type} test;
                if (${Type}.TryParse(Attributes[""${Attribute}""], out test))
                {
                    return test;
                }

                // the default
                return ${DefaultValue};
            }
        }
        ";

        const string attributeStringGetterTemplate = @"
        public ${Type} ${AttributeMethodName}Attribute
        {
            get
            {
                return Attributes[""${Attribute}""];
            }
        }
        ";


        /*
         public string AbbrAttribute
        {
            get
            {
                return Attributes["abbr"];
            }
        }
         */

        /*
        public ${Type} ${AttributeMethodName}Attribute
        {
            get
            {
                ${Type} test;
                if (${Type}.TryParse(Attributes["${Attribute}"], out test))
                {
                    return test;
                }

                // the default
                return ${DefaultValue};
            }
        }
        */

        public string ClassName { get; private set; }
        public StringBuilder ClassContent { get; private set; }
        public List<Attribute> Attributes { get; private set; }

        public AttributeMethodGenerator(string className, StringBuilder classContent, List<Attribute> attributes)
        {
            ClassName = className;
            ClassContent = classContent;
            Attributes = attributes;
        }

        public StringBuilder Generate()
        {
            ClassContent = GenerateAttributeMethods(attributeMethodTemplate, "${attributes}");

            ClassContent = GenerateAttributeMethods(genericAttribuiteMethodTemplate, "${genericAttributes}");

            ClassContent = GenerateAttributeGetters("${attributeGetters}");

            return ClassContent;
        }

        private StringBuilder GenerateAttributeGetters(string ToReplace)
        {
            
            StringBuilder sb = new StringBuilder();
            foreach (Attribute a in Attributes)
            {
                var defaultValue = a.Default;
                if(string.IsNullOrWhiteSpace(a.Default))
                {
                    defaultValue = "\"\"";
                }

                string template = a.ClrType == "int" ? attributeIntGetterTemplate :
                    attributeStringGetterTemplate;
                
                sb.Append(
                    template
                        .Replace("${Class}", ClassName)
                        .Replace("${AttributeMethodName}", CSharpNaming.ClassifyName(a.Name))
                        .Replace("${Attribute}", a.Name)
                        .Replace("${Type}", a.ClrType)
                        .Replace("${DefaultValue}", defaultValue)
                );

            };
            return ClassContent.Replace(ToReplace, sb.ToString());

        }

        private StringBuilder GenerateAttributeMethods(string template, string ToReplace)
        {
            StringBuilder sb = new StringBuilder();
            foreach (Attribute a in Attributes)
            {
                string processing = GenProcessingCode(a);

                sb.Append(
                    template
                        .Replace("${Class}", ClassName)
                        .Replace("${AttributeMethodName}", CSharpNaming.ClassifyName(a.Name))
                        .Replace("${Attribute}", a.Name)
                        .Replace("${Type}", a.ClrType)
                        .Replace("${processing}", processing)
                );

            };
            return ClassContent.Replace(ToReplace, sb.ToString());

        }

        private static string GenProcessingCode(Attribute a)
        {
            string processing = "";

            if (a.XmlType == "URI")
            {
                processing = @"
            if(!value.StartsWith(""#""))
            {
                value = ResolveUrl(value);
            }
                    ";
            }
            return processing;
        }
    }
}
